﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GraphTest.Geometry2D.Interfaces;
using System.Drawing;

namespace GraphTest.Geometry2D
{
    public class Rectangle2D
    {
        public Point2D Location { get; set; }
        public Vector2D Size { get; set; }

        public float X { get { return Location.X; } }
        public float Y { get { return Location.Y; } }
        public float Width { get { return Size.X; } }
        public float Height { get { return Size.Y; } }
        
        public float Left { get { return Location.X; } }
        public float Right { get { return Location.X + Size.X; } }
        public float Top { get { return Location.Y; } }
        public float Bottom { get { return Location.Y + Size.Y; } }



        public Rectangle2D()
        {
            Location = new Point2D(0.0F, 0.0F);
            Size = new Vector2D(0.0F, 0.0F);
        }

        public Rectangle2D(IPoint2D location, IPoint2D size)
        {
            Location = new Point2D(location);
            Size = new Vector2D(size);
        }

        public Rectangle2D(float x, float y, float width, float height)
            : this(new Point2D(x, y), new Vector2D(width, height))
        { }


        public Rectangle GetRectangle()
        {
            return new Rectangle((int)X, (int)Y, (int)Width, (int)Height);
        }


        public Segment2D[] GetSegments()
        {
            Segment2D[] result = new Segment2D[4];

            Point2D P1 = new Point2D(X, Y);
            Point2D P2 = new Point2D(X + Width, Y);
            Point2D P3 = new Point2D(X + Width, Y + Height);
            Point2D P4 = new Point2D(X, Y + Height);

            result[0] = new Segment2D(P1, P2);
            result[1] = new Segment2D(P2, P3);
            result[2] = new Segment2D(P3, P4);
            result[3] = new Segment2D(P4, P1);

            return result;
        }

        public static Segment2D[] GetSegments(Rectangle2D r)
        {
            return r.GetSegments();
        }

        public bool Contains(float x, float y)
        {
            bool result = true;
            
            result &= Left <= x && x <= Right;
            result &= Top <= y && y <= Bottom;

            return result;
        }

        public bool IsRectanglesIntersected(Rectangle2D r)
        {
            if (r == null)
                throw new ArgumentNullException("r");

            bool result = false;

            result |= Contains(r.Left, r.Top)
                    || Contains(r.Left + r.Width, r.Top)
                    || Contains(r.Left + r.Width, r.Top + r.Height)
                    || Contains(r.Left, r.Top + r.Height);

            if (result)
                return result;

            Segment2D[] segments1 = GetSegments();
            Segment2D[] segments2 = r.GetSegments();

            foreach (var s1 in segments1)
                foreach (var s2 in segments2)
                {
                    bool? check = Segment2D.IsNormalSegmentsIntersected(s1, s2);
                    if (check.HasValue && check.Value)
                        return true;
                }

            return false;
        }

        public static bool IsRectanglesIntersected(Rectangle2D r1, Rectangle2D r2)
        {
            if (r1 == null)
                throw new ArgumentNullException("r1");

            if (r2 == null)
                throw new ArgumentNullException("r2");

            return r1.IsRectanglesIntersected(r2);
        }

        public Segment2D[] GetShiftSegments(Vector2D shift)
        {
            Segment2D[] result = new Segment2D[4];

            Point2D P1 = new Point2D(X, Y);
            Point2D P2 = new Point2D(X + Width, Y);
            Point2D P3 = new Point2D(X + Width, Y + Height);
            Point2D P4 = new Point2D(X, Y + Height);

            Point2D P1shift = new Point2D(P1.X + shift.X, P1.Y + shift.Y);
            Point2D P2shift = new Point2D(P2.X + shift.X, P2.Y + shift.Y);
            Point2D P3shift = new Point2D(P3.X + shift.X, P3.Y + shift.Y);
            Point2D P4shift = new Point2D(P4.X + shift.X, P4.Y + shift.Y);

            result[0] = new Segment2D(P1, P1shift);
            result[1] = new Segment2D(P2, P2shift);
            result[2] = new Segment2D(P3, P3shift);
            result[3] = new Segment2D(P4, P4shift);

            return result;
        }


    }
}
